/**
 * 项目名：五位一体化工安全信息平台
 * 日期：    2019-12-08 15:07:43
 * Copyright (c) 2015- joysuch-版权所有
 */

package com.joysuch.wwyt.bp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.databind.ser.Serializers;
import com.google.common.collect.Lists;
import com.joysuch.wwyt.bp.bean.contractor.BpContractorBean;
import com.joysuch.wwyt.bp.bean.contractor.BpContractorViolationRecordBean;
import com.joysuch.wwyt.bp.entity.contractor.BpContractor;
import com.joysuch.wwyt.bp.entity.contractor.BpContractorViolationRecord;
import com.joysuch.wwyt.bp.enums.DataStateTypes;
import com.joysuch.wwyt.bp.mapper.BpContractorViolationRecordsManagementMapper;
import com.joysuch.wwyt.bp.repository.BpContractorViolationRecordManagementDao;
import com.joysuch.wwyt.bp.service.BpContractorService;
import com.joysuch.wwyt.bp.service.BpContractorViolationRecordsManagementService;
import com.joysuch.wwyt.core.bean.BaseAttachmentBean;
import com.joysuch.wwyt.core.bean.SimpleInfoBean;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.util.JsonUtil;
import com.joysuch.wwyt.core.common.util.PageDataUtils;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.entity.BaseTypeGroupItem;
import com.joysuch.wwyt.core.repository.BaseTypeGroupItemDao;
import com.joysuch.wwyt.core.entity.BaseTypeGroup;
import com.joysuch.wwyt.core.entity.BaseTypeGroupItem;
import com.joysuch.wwyt.core.repository.BaseTypeGroupDao;
import com.joysuch.wwyt.core.service.BaseConfigService;
import com.joysuch.wwyt.core.service.BizCodeGeneratorFacade;
import com.joysuch.wwyt.edu.entity.EduTrainningRecordUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.util.Assert;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.*;
import java.util.stream.Collectors;

@Service
//@Transactional(rollbackFor = Exception.class)
@Slf4j
public class BpContractorViolationRecordsManagementServiceImpl implements BpContractorViolationRecordsManagementService {

    @Autowired
    private BpContractorViolationRecordManagementDao dao;
    @Autowired
    private BpContractorService contractorService;
    @Autowired
    private BizCodeGeneratorFacade bizCodeGeneratorFacade;
    @Resource
    private BpContractorViolationRecordsManagementMapper bpContractorViolationRecordsManagementMapper;
//    @Resource
//    private BaseConfigService baseConfigService;

    @Resource
    private BaseTypeGroupDao typeGroupDao;

    @Autowired
    private BaseTypeGroupItemDao baseTypeGroupItemDao;

    @Override
    public Page<BpContractorViolationRecordBean> page(Pageable page, String contractorName) {
        page = PageDataUtils.addOrderByDesc(page, "id");
        Page<BpContractorViolationRecord> list = null;
        // 根据姓名获取承包商id
        if (contractorName != null) {
            List<Long> idsByName = contractorService.findIdsByName(contractorName);
            if (idsByName == null || idsByName.size() <= 0) {
                List<BpContractorViolationRecordBean> resultList = Lists.newArrayList();
                return new PageImpl<>(resultList, page, 0);
            }
            Specification<BpContractorViolationRecord> specification = (Root<BpContractorViolationRecord> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) -> {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(cb.equal(root.get("state"), DataStateTypes.EFFECTIVE.getState()));
                CriteriaBuilder.In<Object> in = cb.in(root.get("contractorId"));
                for (Long id : idsByName) {
                    in.value(id);
                }
                predicates.add(in);
                return cb.and(predicates.toArray(new Predicate[predicates.size()]));
            };
            list = dao.findAll(specification, page);
        } else {
            list = dao.findAll(page);
        }

        List<BpContractorViolationRecordBean> resultList = Lists.newArrayList();
        if (list!=null&&!list.isEmpty()) {
            for (BpContractorViolationRecord entity : list) {
                BpContractorViolationRecordBean bean = new BpContractorViolationRecordBean();
                BeanUtils.copyProperties(entity, bean);
                if (!StringUtils.isEmpty(entity.getAttachment()) && !"null".equals(entity.getAttachment())) {
                    bean.setAttachment(JsonUtil.fromListJson(entity.getAttachment(), BaseAttachmentBean.class));
                }
                log.info("根据承包商id{}查询承包商信息", entity.getContractorId());
                ResultBean resultBean = contractorService.getById(entity.getContractorId());
                BpContractorBean contractorBean = (BpContractorBean) resultBean.getData();
                bean.setContractor(contractorBean);
                bean.setContractorName(contractorBean.getCompanyName());
                if (entity.getViolationType() != null) {
                    Optional<BaseTypeGroupItem> op = baseTypeGroupItemDao.findById((long)entity.getViolationType().intValue());
                    if (op.isPresent()) {
                        bean.setViolationTypeName(op.get().getName());
                        bean.setViolationType(entity.getViolationType());
                    }
                }

                resultList.add(bean);
            }
        }

        return new PageImpl<>(resultList, page, list==null?0:list.getTotalElements());
    }

    @Override
    public ResultBean getById(Long id) {
        Assert.notNull(id, "id cannot be null");
        //查询违章记录表
        BpContractorViolationRecord entity = dao.findById(id).orElseThrow(() -> new IllegalArgumentException("此数据不存在"));
        BpContractorViolationRecordBean bean = new BpContractorViolationRecordBean();
        bean.setAttachment(JsonUtil.fromListJson(entity.getAttachment(), BaseAttachmentBean.class));
        bean.setAttachment(JsonUtil.fromListJson(entity.getAttachment(),BaseAttachmentBean.class));

        if (entity.getViolationType() != null) {
            Optional<BaseTypeGroupItem> op = baseTypeGroupItemDao.findById((long)entity.getViolationType().intValue());
            if (op.isPresent()) {
                bean.setViolationTypeName(op.get().getName());
                bean.setViolationType(entity.getViolationType());
            }
        }

        BeanUtils.copyProperties(entity, bean);
        //查询承包商信息
        if (entity != null && entity.getContractorId() != null) {
            log.info("根据承包商id{}查询承包商信息", entity.getContractorId());
            ResultBean resultBean = contractorService.getById(entity.getContractorId());
            BpContractorBean contractorBean = (BpContractorBean) resultBean.getData();
            bean.setContractor(contractorBean);
            bean.setContractorName(contractorBean.getCompanyName());
        }
        return ResultBean.success(bean);
    }

    @Override
//    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public ResultBean save(BpContractorViolationRecordBean bean) {
        Long id = bean.getId();
        BpContractorViolationRecord entity;
        if (id == null) {
            log.info("开始新增违章记录");
            entity = new BpContractorViolationRecord();
            entity.setCode(bizCodeGeneratorFacade.chengbaoshangweishangjilu());
            entity.setState(DataStateTypes.EFFECTIVE.getState());
        } else {
            log.info("开始修改施工记录");
            entity = dao.findById(id).orElseThrow(() -> new IllegalArgumentException("系统繁忙"));
            if (DataStateTypes.UN_EFFECTIVE.getState().equals(entity.getState())) {
                return ResultBean.fail(101, "此数据已作废");
            }
        }
        entity.setAttachment(JsonUtil.toJson(bean.getAttachment()));
        BeanUtils.copyProperties(bean, entity, "code", "state");
        BpContractorViolationRecord save = dao.save(entity);
        return ResultBean.defaultSuccessResult();
    }

    @Override
//    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public ResultBean delete(Long id) {
        Assert.notNull(id, "id cannot be null");
        BpContractorViolationRecord entity = dao.findById(id).orElseThrow(() -> new IllegalArgumentException("此数据不存在"));
        dao.delete(entity);
        return ResultBean.defaultSuccessResult();
    }


    private List<BaseTypeGroupItem> getViolationType() {
        BaseTypeGroup typeGroup = typeGroupDao.findByCode("WZLX");
        if (typeGroup == null) {
            throw new IllegalArgumentException("字典表未配置违章类型");
        }
        Set<BaseTypeGroupItem> items = typeGroup.getBaseTypeGroupItems();
        List<BaseTypeGroupItem> list = Lists.newArrayList();
        if (items != null) {
            list.addAll(items);
        }
        return list.stream().filter(e -> e.getState() == DataStateTypes.EFFECTIVE.getState()).collect(Collectors.toList());
    }

    /**
     * @param
     * @param beginTime
     * @param endTime
     * @return
     */
    @Override
    public IPage<BpContractorViolationRecordBean> getViolationRecordsByContractor(String contractorName, Date beginTime, Date endTime, Integer pageNo, Integer pageSize) {
        IPage<BpContractorViolationRecordBean> bpContractorViolationRecordBeanPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageNo, pageSize);
        Page<SimpleInfoBean> simpleInfoBeans = contractorService.simplePage(PageRequest.of(pageNo - 1, pageSize), contractorName);
        List<SimpleInfoBean> content = simpleInfoBeans.getContent();
        List<BpContractorViolationRecordBean> violationRecordBeans = new ArrayList<>();

        //查询所有违章类型
        List<BaseTypeGroupItem> violationTypes = getViolationType();

        for (SimpleInfoBean simpleInfoBean : content) {
            // 承包商名称  simpleInfoBean.name
            // 违章次数   违章记录: 从承包商记录表里面查询承包商记 -> 查询条件 承包商ID 开始、结束时间  selectCountXXX
//            bpContractorViolationRecordsManagementMapper.selectCount()
            // 累计罚款金额    从违章记录表 sum（处罚金额） -> 承包商ID  开始、结束时间
            // 累计扣分     从违章记录表 sum（处罚积分） -> 承包商ID  开始、结束时间
            // 违章详情     先查出所有违章类型
            //                  遍历违章类型 -》 从违章记录表 count(1) -> 承包商ID  开始、结束时间 、 违章类型

            List<BpContractorViolationRecord> violationRecordList = bpContractorViolationRecordsManagementMapper.selectRecordsByContractor(simpleInfoBean.getId(), beginTime, endTime);
            BpContractorViolationRecordBean bp = new BpContractorViolationRecordBean();
            if (violationRecordList.size() == 0) {
                bp.setContractorName(simpleInfoBean.getName());
                bp.setViolationCount(0);
                bp.setViolationAmount(0.0);
                bp.setViolationIntegral(0.0);
                bp.setBeginTime(beginTime);
                bp.setEndTime(endTime);
                bp.setViolationDetail("无违章记录");
                violationRecordBeans.add(bp);
            } else {
                BpContractorViolationRecord record = violationRecordList.get(0);
                bp.setContractorName(record.getContractorName());
                bp.setViolationCount(record.getViolationCount());
                bp.setViolationAmount(record.getViolationAmount());
                bp.setViolationIntegral(record.getViolationIntegral());
                bp.setBeginTime(beginTime);
                bp.setEndTime(endTime);

                String violationDetail = "";
                for (BaseTypeGroupItem violationType : violationTypes) {
                    LambdaQueryWrapper<BpContractorViolationRecord> queryWrapper = new LambdaQueryWrapper<BpContractorViolationRecord>()
                            .eq(BpContractorViolationRecord::getViolationType, (int) violationType.getId().longValue())
                            .eq(BpContractorViolationRecord::getContractorId, simpleInfoBean.getId())
                            .eq(BpContractorViolationRecord::getDeleteFlag, "0");
                    if (beginTime != null) {
                        queryWrapper.ge(BpContractorViolationRecord::getViolatorDate, beginTime);
                    }
                    if (endTime != null) {
                        queryWrapper.lt(BpContractorViolationRecord::getViolatorDate, endTime);
                    }
                    Integer count = bpContractorViolationRecordsManagementMapper.selectCount(queryWrapper);
                    if (violationDetail.length() != 0) {
                        violationDetail += ", ";
                    }
                    violationDetail += violationType.getName() + ":" + count + "次";
                }
                bp.setViolationDetail(violationDetail);
                violationRecordBeans.add(bp);
            }
        }
        bpContractorViolationRecordBeanPage.setRecords(violationRecordBeans);
        bpContractorViolationRecordBeanPage.setTotal(simpleInfoBeans.getTotalElements());
        return bpContractorViolationRecordBeanPage;
    }
}
